package service

import (
	"context"
	"fmt"
	"math"
	"strconv"
	"strings"
	"time"

	"WHY_GIN/config"
	"WHY_GIN/models"
	"github.com/adshao/go-binance/v2"
	"github.com/shopspring/decimal"
)

// AccountBalance 账户余额信息
type AccountBalance struct {
	Asset  string  // 资产名称
	Free   float64 // 可用余额
	Locked float64 // 冻结余额
}

// getAccountBalance 获取账户余额信息
func getAccountBalance(client *binance.Client) ([]AccountBalance, error) {
	fmt.Printf("[DEBUG] 正在获取账户余额信息...\n")
	
	// 调用账户信息API
	account, err := client.NewGetAccountService().Do(context.Background())
	if err != nil {
		fmt.Printf("[ERROR] 获取账户信息失败: %v\n", err)
		return nil, err
	}
	
	var balances []AccountBalance
	
	// 遍历所有余额，只保留有余额的资产
	for _, balance := range account.Balances {
		free, err := strconv.ParseFloat(balance.Free, 64)
		if err != nil {
			continue
		}
		locked, err := strconv.ParseFloat(balance.Locked, 64)
		if err != nil {
			continue
		}
		
		// 只记录有余额的资产（可用余额或冻结余额大于0）
		if free > 0 || locked > 0 {
			balances = append(balances, AccountBalance{
				Asset:  balance.Asset,
				Free:   free,
				Locked: locked,
			})
		}
	}
	
	fmt.Printf("[DEBUG] 成功获取 %d 个有余额的资产\n", len(balances))
	return balances, nil
}

// printAccountBalance 打印账户余额信息
func printAccountBalance(client *binance.Client) {
	balances, err := getAccountBalance(client)
	if err != nil {
		fmt.Printf("[ERROR] 无法获取账户余额: %v\n", err)
		return
	}
	
	fmt.Println("\n=== 账户余额信息 ===")
	if len(balances) == 0 {
		fmt.Println("[INFO] 账户暂无余额")
		return
	}
	
	for _, balance := range balances {
		total := balance.Free + balance.Locked
		fmt.Printf("[BALANCE] %s: 总计=%.8f (可用=%.8f, 冻结=%.8f)\n", 
			balance.Asset, total, balance.Free, balance.Locked)
	}
	fmt.Println("========================\n")
}

// printTradingPairBalance 打印交易对相关的账户余额
func printTradingPairBalance(client *binance.Client, symbol string) {
	// 从交易对符号中提取基础资产和报价资产
	// 例如：DOGEUSDT -> DOGE, USDT
	var baseAsset, quoteAsset string
	if len(symbol) >= 6 && symbol[len(symbol)-4:] == "USDT" {
		baseAsset = symbol[:len(symbol)-4]
		quoteAsset = "USDT"
	} else if len(symbol) >= 6 && symbol[len(symbol)-3:] == "BTC" {
		baseAsset = symbol[:len(symbol)-3]
		quoteAsset = "BTC"
	} else if len(symbol) >= 6 && symbol[len(symbol)-3:] == "ETH" {
		baseAsset = symbol[:len(symbol)-3]
		quoteAsset = "ETH"
	} else {
		// 默认处理，假设最后4个字符是报价资产
		if len(symbol) > 4 {
			baseAsset = symbol[:len(symbol)-4]
			quoteAsset = symbol[len(symbol)-4:]
		} else {
			fmt.Printf("[WARNING] 无法解析交易对 %s\n", symbol)
			return
		}
	}
	
	fmt.Printf("\n=== %s 交易对余额 ===\n", symbol)
	
	// 获取基础资产余额
	baseBalance, err := getSpecificAssetBalance(client, baseAsset)
	if err != nil {
		fmt.Printf("[ERROR] 获取 %s 余额失败: %v\n", baseAsset, err)
	} else {
		baseTotal := baseBalance.Free + baseBalance.Locked
		fmt.Printf("[BALANCE] %s: 总计=%.8f (可用=%.8f, 冻结=%.8f)\n", 
			baseAsset, baseTotal, baseBalance.Free, baseBalance.Locked)
	}
	
	// 获取报价资产余额
	quoteBalance, err := getSpecificAssetBalance(client, quoteAsset)
	if err != nil {
		fmt.Printf("[ERROR] 获取 %s 余额失败: %v\n", quoteAsset, err)
	} else {
		quoteTotal := quoteBalance.Free + quoteBalance.Locked
		fmt.Printf("[BALANCE] %s: 总计=%.8f (可用=%.8f, 冻结=%.8f)\n", 
			quoteAsset, quoteTotal, quoteBalance.Free, quoteBalance.Locked)
	}
	
	fmt.Println("========================\n")
}

// getSpecificAssetBalance 获取特定资产的余额
func getSpecificAssetBalance(client *binance.Client, asset string) (*AccountBalance, error) {
	balances, err := getAccountBalance(client)
	if err != nil {
		return nil, err
	}
	
	for _, balance := range balances {
		if balance.Asset == asset {
			return &balance, nil
		}
	}
	
	// 如果没有找到该资产，返回零余额
	return &AccountBalance{
		Asset:  asset,
		Free:   0,
		Locked: 0,
	}, nil
}

// adjustPriceToTickSize 调整价格以符合价格过滤器要求
func adjustPriceToTickSize(price float64, tickSize string) (string, error) {
	tick, err := strconv.ParseFloat(tickSize, 64)
	if err != nil {
		return "", err
	}

	// 将价格调整为tickSize的倍数
	adjustedPrice := math.Round(price/tick) * tick

	// 根据tickSize确定小数位数
	var precision int
	if tick >= 1 {
		precision = 0
	} else {
		tickStr := fmt.Sprintf("%.8f", tick)
		// 计算小数点后的位数
		parts := strings.Split(tickStr, ".")
		if len(parts) == 2 {
			precision = len(strings.TrimRight(parts[1], "0"))
		}
	}

	return fmt.Sprintf("%.*f", precision, adjustedPrice), nil
}

// checkDuplicateOrder 检查是否已存在相同价格的订单
func checkDuplicateOrder(client *binance.Client, symbol string, side binance.SideType, priceStr string) (bool, error) {
	fmt.Printf("[DEBUG] 检查重复订单: %s %s @ %s\n", side, symbol, priceStr)
	
	// 获取当前未完成的订单
	orders, err := client.NewListOpenOrdersService().Symbol(symbol).Do(context.Background())
	if err != nil {
		fmt.Printf("[ERROR] 获取未完成订单失败: %v\n", err)
		return false, err
	}
	
	fmt.Printf("[DEBUG] 当前未完成订单数量: %d\n", len(orders))
	
	// 检查是否存在相同价格和方向的订单
	for _, order := range orders {
		if order.Side == side && order.Price == priceStr {
			fmt.Printf("[DEBUG] 发现重复订单: OrderID=%d, Side=%s, Price=%s\n", order.OrderID, order.Side, order.Price)
			return true, nil
		}
	}
	
	fmt.Printf("[DEBUG] 未发现重复订单，可以下单\n")
	return false, nil
}

// PlaceLimitOrderWithClient 使用指定客户端下限价单（供调度器使用）
func PlaceLimitOrderWithClient(client *binance.Client, symbol string, side binance.SideType, price float64, quantity int, tickSize string) error {
	fmt.Printf("[DEBUG] 正在调用下单 API: %s %s, 原始价格: %.8f, 数量: %d\n", side, symbol, price, quantity)
	return PlaceLimitOrderWithFloatQuantity(client, symbol, side, price, float64(quantity), tickSize)
}

// PlaceLimitOrderWithFloatQuantity 使用指定客户端下限价单（支持浮点数量）
func PlaceLimitOrderWithFloatQuantity(client *binance.Client, symbol string, side binance.SideType, price float64, quantity float64, tickSize string) error {
	fmt.Printf("[DEBUG] 正在调用下单 API: %s %s, 原始价格: %.8f, 数量: %.2f\n", side, symbol, price, quantity)

	// 调整价格以符合价格过滤器
	adjustedPriceStr, err := adjustPriceToTickSize(price, tickSize)
	if err != nil {
		fmt.Printf("[ERROR] 价格调整失败: %v\n", err)
		return err
	}
	fmt.Printf("[DEBUG] 调整后价格: %s (tickSize: %s)\n", adjustedPriceStr, tickSize)

	// 检查是否已存在相同价格的订单
	exists, err := checkDuplicateOrder(client, symbol, side, adjustedPriceStr)
	if err != nil {
		fmt.Printf("[ERROR] 检查重复订单失败: %v\n", err)
		return err
	}
	if exists {
		fmt.Printf("[WARNING] 已存在相同价格的%s订单(%.8f)，跳过下单\n", side, price)
		return fmt.Errorf("禁止重复下单：已存在相同价格的%s订单", side)
	}

	// 如果是买入订单，检查USDT余额是否足够
	if side == binance.SideTypeBuy {
		usdtBalance, err := getSpecificAssetBalance(client, "USDT")
		if err != nil {
			fmt.Printf("[ERROR] 获取USDT余额失败: %v\n", err)
			return err
		}
		
		// 计算所需USDT金额
		requiredUSDT := price * quantity
		if usdtBalance.Free < requiredUSDT {
			fmt.Printf("[WARNING] USDT余额不足(%.2f < %.2f)，跳过买入订单\n", usdtBalance.Free, requiredUSDT)
			return fmt.Errorf("USDT余额不足，当前可用余额: %.2f USDT，需要: %.2f USDT", usdtBalance.Free, requiredUSDT)
		}
		
		fmt.Printf("[INFO] USDT余额检查通过，可用余额: %.2f USDT，需要: %.2f USDT\n", usdtBalance.Free, requiredUSDT)
	}
	
	// 如果是卖出订单，检查基础资产余额是否足够
	if side == binance.SideTypeSell {
		// 从交易对中提取基础资产名称（如DOGEUSDT中的DOGE）
		baseAsset := strings.TrimSuffix(symbol, "USDT")
		assetBalance, err := getSpecificAssetBalance(client, baseAsset)
		if err != nil {
			fmt.Printf("[ERROR] 获取%s余额失败: %v\n", baseAsset, err)
			return err
		}
		
		// 检查可用资产余额是否少于下单数量
		if assetBalance.Free < quantity {
			fmt.Printf("[WARNING] %s余额不足(%.2f < %.2f)，跳过卖出订单\n", baseAsset, assetBalance.Free, quantity)
			return fmt.Errorf("%s余额不足，当前可用余额: %.2f %s，需要: %.2f %s", baseAsset, assetBalance.Free, baseAsset, quantity, baseAsset)
		}
		
		fmt.Printf("[INFO] %s余额检查通过，可用余额: %.2f %s，需要: %.2f %s\n", baseAsset, assetBalance.Free, baseAsset, quantity, baseAsset)
	}

	// 执行下单
	orderResult, err := client.NewCreateOrderService().
		Symbol(symbol).
		Side(side).
		Type(binance.OrderTypeLimit).
		TimeInForce(binance.TimeInForceTypeGTC).
		Price(adjustedPriceStr).
		Quantity(fmt.Sprintf("%.8f", quantity)).
		Do(context.Background())
	if err != nil {
		fmt.Printf("[ERROR] 下单 API 调用失败: %v\n", err)
		return err
	}

	// 下单成功后记录交易信息到数据库
	if orderResult != nil {
		err = saveTradeRecordFloat(orderResult, symbol, side, price, quantity)
		if err != nil {
			fmt.Printf("[WARNING] 交易记录保存失败: %v\n", err)
			// 不返回错误，避免影响交易流程
		}
	}

	return nil
}

// ParseFloat 解析浮点数字符串（供调度器使用）
func ParseFloat(s string) (float64, error) {
	return strconv.ParseFloat(s, 64)
}

// saveTradeRecord 保存交易记录到数据库
func saveTradeRecord(orderResult *binance.CreateOrderResponse, symbol string, side binance.SideType, price float64, quantity int) error {
	return saveTradeRecordFloat(orderResult, symbol, side, price, float64(quantity))
}

// saveTradeRecordFloat 保存交易记录到数据库（支持浮点数量）
func saveTradeRecordFloat(orderResult *binance.CreateOrderResponse, symbol string, side binance.SideType, price float64, quantity float64) error {
	// 确定交易类型
	var actionType int
	if side == binance.SideTypeBuy {
		actionType = 1 // 买入
	} else {
		actionType = 2 // 卖出
	}

	// 转换价格和数量为decimal类型
	priceDecimal := decimal.NewFromFloat(price)
	quantityDecimal := decimal.NewFromFloat(quantity)
	amountDecimal := priceDecimal.Mul(quantityDecimal)

	// 获取当前余额（这里可以调用账户余额查询API，暂时设为0）
	usdtBalance := decimal.NewFromInt(0)
	coinBalance := decimal.NewFromInt(0)

	// 创建交易记录
	tradeRecord := models.TradeRecord{
		ConfigID:    1, // 暂时设为1，后续可以根据实际配置ID设置
		LevelID:     nil, // 网格层级暂时为空
		TradeTime:   time.Now(),
		ActionType:  actionType,
		Price:       priceDecimal,
		Quantity:    quantityDecimal,
		Amount:      amountDecimal,
		Fee:         decimal.NewFromInt(0), // 手续费暂时设为0
		FeeCurrency: "USDT",
		USDTBalance: usdtBalance,
		CoinBalance: coinBalance,
		OrderID:     fmt.Sprintf("%d", orderResult.OrderID),
		Comment:     fmt.Sprintf("网格交易-%s-%s", symbol, side),
	}

	// 保存到数据库
	result := config.DB.Create(&tradeRecord)
	if result.Error != nil {
		return fmt.Errorf("保存交易记录失败: %v", result.Error)
	}

	fmt.Printf("[SUCCESS] 交易记录已保存到数据库，记录ID: %d, 订单ID: %s\n", tradeRecord.ID, tradeRecord.OrderID)
	return nil
}